package com.xbts.system.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaweicloud.sdk.bss.v2.model.PeriodProductInfo;
import com.huaweicloud.sdk.core.utils.JsonUtils;
import com.huaweicloud.sdk.ecs.v2.model.*;
import com.xbts.common.constant.UserConstants;
import com.xbts.common.core.domain.AjaxResult;
import com.xbts.common.core.domain.entity.SysUser;
import com.xbts.common.core.domain.model.LoginUser;
import com.xbts.common.core.redis.RedisDelayQueueHandle;
import com.xbts.common.enums.EmailTypeEnum;
import com.xbts.common.enums.ServerStatusEnum;
import com.xbts.common.enums.ShoppingCarEnums;
import com.xbts.common.utils.SecurityUtils;
import com.xbts.common.utils.SnowFlakeUtil;
import com.xbts.common.utils.StringUtils;
import com.xbts.common.utils.bean.BeanUtils;
import com.xbts.system.domain.*;
import com.xbts.system.domain.dto.EmailSendDTO;
import com.xbts.system.domain.dto.ListServersDetailsRequestDTO;
import com.xbts.system.domain.dto.RateOnPeriodReqDTO;
import com.xbts.system.enums.OrderStatusEnum;
import com.xbts.system.enums.OrderTypeEnum;
import com.xbts.system.mapper.CnUserCloudServersRelationMapper;
import com.xbts.system.mapper.SysUserMapper;
import com.xbts.system.module.payment.enums.PaymentMethodEnum;
import com.xbts.system.module.payment.service.ICnWalletLogService;
import com.xbts.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户-弹性云服务器关系Service业务层处理
 *
 * @author xbts
 * @date 2023-08-03
 */
@Slf4j
@Service
public class CnUserCloudServersRelationServiceImpl extends ServiceImpl<CnUserCloudServersRelationMapper, CnUserCloudServersRelation> implements ICnUserCloudServersRelationService , RedisDelayQueueHandle<String> {

    @Autowired
    private ICloudControlService cloudControlService;
    @Autowired
    private ICnShoppingCarService cnShoppingCarService;
    @Autowired
    private ICnOrderItemService orderItemService;
    @Autowired
    private ICnOrderService orderService;
    @Autowired
    private ICnGovernmentCloudService governmentCloudService;
    @Autowired
    private ICnCloudMarketSkuService cnCloudMarketSkuService;
    @Autowired
    private ISysMessageService sysMessageService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private ICnWalletLogService cnWalletLogService;
    @Autowired
    private ICloudServiceService cloudServiceService;

    @Autowired
    private EmailSendService emailSendService;

    /**
     * 查询用户-弹性云服务器关系列表
     *
     * @param cnUserCloudServersRelation 用户-弹性云服务器关系
     * @return 用户-弹性云服务器关系
     */
    @Override
    public List<CnUserCloudServersRelation> selectCnUserCloudServersRelationList(CnUserCloudServersRelation cnUserCloudServersRelation) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (!loginUser.getUser().getUserType().equals(UserConstants.USER_TYPE_MANAGER)) {
            // 查询用户购买的服务器
            cnUserCloudServersRelation.setUserId(SecurityUtils.getUserId());
        }

        Map<String, Object> params = cnUserCloudServersRelation.getParams();
        if(params != null && params.size() > 0){
            int pageSize = (int) params.get("pageSize");
            int pageNum = (int) params.get("pageNum");
            cnUserCloudServersRelation.setOffset(pageSize * (pageNum - 1));
            cnUserCloudServersRelation.setPageSize(pageSize);
        }

        List<CnUserCloudServersRelation> relationList = baseMapper.selectCnUserCloudServersRelationList(cnUserCloudServersRelation);

        List<CnRegion> cnRegions = cloudServiceService.regionList();
        Map<String, String> regionMap = cnRegions.stream().collect(Collectors.toMap(CnRegion::getRegionId, CnRegion::getRegionName));

        // 在华为云上查询云服务器信息
        if (relationList != null && relationList.size() > 0) {
            List<CnUserCloudServersRelation> result = new ArrayList<>(relationList.size());
            // 从json中获取服务器状态
            for (CnUserCloudServersRelation userCloudServersRelation : relationList) {
                CnUserCloudServersRelation relationVO = new CnUserCloudServersRelation();
                BeanUtils.copyBeanProp(relationVO, userCloudServersRelation);
                relationVO.setServersJsonStr(userCloudServersRelation.getJsonStr());
                result.add(relationVO);

                CnOrderItem orderItem = orderItemService.getById(userCloudServersRelation.getOrderItemId());
                relationVO.setCloudServerJsonStr(orderItem.getJsonStr());
                relationVO.setPrice(orderItem.getUpdatePrice().doubleValue());

                String jsonStr = userCloudServersRelation.getJsonStr();
                ListServersDetailsResponse response = JsonUtils.toObject(jsonStr, ListServersDetailsResponse.class);
                if(response != null) {
                    List<ServerDetail> servers = response.getServers();
                    if (servers != null && servers.size() > 0) {
                        ServerDetail serverDetail = servers.get(0);
//                    String status = serverDetail.getStatus();
//                    relationVO.setStatus(ServerStatusEnum.getByName(status));
                        // 获取服务器ip
                        Map<String, List<ServerAddress>> addresses = serverDetail.getAddresses();
                        List<ServerAddress> collect = addresses.values().stream().flatMap(List::stream).collect(Collectors.toList());
                        List<ServerAddress> addressList = collect.stream()
                                .filter(serverAddress -> ServerAddress.OsEXTIPSTypeEnum.FLOATING.equals(serverAddress.getOsEXTIPSType())).collect(Collectors.toList());
                        relationVO.setIp(addressList.get(0).getAddr());
                        relationVO.setRegionId(regionMap.get(serverDetail.getOsEXTAZAvailabilityZone().substring(0, serverDetail.getOsEXTAZAvailabilityZone().length() - 1)));
                        // 拼接配置信息
                        String config = "规格：" + serverDetail.getMetadata().get("metering.resourcespeccode");
                        config += "，vcpus：" + serverDetail.getFlavor().getVcpus();
                        config += "，内存：" + (Integer.parseInt(serverDetail.getFlavor().getRam()) / 1024) + "G";

                        ListServerBlockDevicesRequest listServerBlockDevicesRequest = new ListServerBlockDevicesRequest();
                        listServerBlockDevicesRequest.setServerId(userCloudServersRelation.getRelationId());
                        AjaxResult ajaxResult = cloudControlService.listServerBlockDevices(listServerBlockDevicesRequest);
                        if(StringUtils.isNotNull(ajaxResult.get("data"))) {
                            ListServerBlockDevicesResponse listServerBlockDevicesResponse = (ListServerBlockDevicesResponse) ajaxResult.get("data");
                            List<ServerBlockDevice> volumeAttachments = listServerBlockDevicesResponse.getVolumeAttachments();
                            for (ServerBlockDevice volumeAttachment : volumeAttachments) {
                                Integer bootIndex = volumeAttachment.getBootIndex();
                                if(bootIndex == 0){
                                    config += "，系统盘：" + volumeAttachment.getSize() + "G";
                                } else {
                                    config += "，数据盘盘：" + volumeAttachment.getSize() + "G";
                                }
                            }
                        }
                        relationVO.setOrderAbstract(config);
                    }
                }
            }
            return result;
        }
        return new ArrayList<>();
    }


    @Override
    public long selectCnUserCloudServersRelationCount(CnUserCloudServersRelation cnUserCloudServersRelation) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (!loginUser.getUser().getUserType().equals(UserConstants.USER_TYPE_MANAGER)) {
            // 查询用户购买的服务器
            cnUserCloudServersRelation.setUserId(SecurityUtils.getUserId());
        }
        long count = baseMapper.selectCnUserCloudServersRelationCount(cnUserCloudServersRelation);
        return count;
    }

    @Transactional
    @Override
    public void autoRenew(String id) {
        // 获取需要付费的资源
        CnUserCloudServersRelation serversRelation = getById(id);
        // 获取资源的信息
        ShoppingCarEnums shoppingCarEnums = serversRelation.getShoppingCarEnums();
        String relationId = serversRelation.getRelationId();
        Long userId = serversRelation.getUserId();
        Integer periodType = serversRelation.getPeriodType();

        // 消息对象
        String title = "资源自动续费结果通知";
        String content = "";
        SysMessage message = new SysMessage();
        message.setUserIds(Collections.singletonList(userId));
        message.setNoticeType(2);
        message.setIsAll(1);
        message.setNoticeTitle(title);

        // 需扣减的余额
        BigDecimal price = BigDecimal.ZERO;
        // 获取资源当前的价格
        if(shoppingCarEnums == ShoppingCarEnums.CLOUD_SERVER){
            // 查询当前规格的价格
            List<PeriodProductInfo> productInfos = JSONArray.parseArray(serversRelation.getPriceQueryJsonStr(), PeriodProductInfo.class);
            productInfos.stream().forEach(v -> {
                v.setPeriodNum(1);
                v.setPeriodType(periodType > 30 ? 3 : 2);
            });
            RateOnPeriodReqDTO vpcDto = new RateOnPeriodReqDTO();
            vpcDto.setProductInfos(productInfos);
            Map<String, Object> stringObjectMap = cloudServiceService.listRateOnPeriodDetail(vpcDto);
            price = (BigDecimal)stringObjectMap.get("price");

        } else if(shoppingCarEnums == ShoppingCarEnums.CLOUD_MARKET){
            CnCloudMarketSku cloudMarketSku = cnCloudMarketSkuService.getById(relationId);
            if(StringUtils.isNull(cloudMarketSku)){
                // 云市场资源不存在 发送信息提醒用户
                content = "【" + serversRelation.getOrderAbstract().split("【")[1].split("】")[0] + "】产品已下架，自动续费失败。如需续费，请联系管理员。";
            }
            price = cloudMarketSku.getPrice();
        } else if(shoppingCarEnums == ShoppingCarEnums.GOV_CLOUD){
            CnGovernmentCloud GovernmentCloud = governmentCloudService.getById(relationId);
            if(StringUtils.isNull(GovernmentCloud)){
                // 政务云资源不存在 发送信息提醒用户
                content = "【" + serversRelation.getOrderAbstract().split("【")[1].split("】")[0] + "】产品已下架，自动续费失败。如需续费，请联系管理员。";
            }

            price = GovernmentCloud.getPrice();
        }
        // 判断余额是否充足
        // 查询用户余额
        price = price.negate();
        SysUser sysUser = userMapper.selectUserById(userId);
        BigDecimal userWallet = sysUser.getUserWallet();
        BigDecimal balance = BigDecimal.ZERO;
        balance = userWallet.add(price);
        if (balance.compareTo(BigDecimal.ZERO) < 0) {
            content = "余额不足，续费失败。当前余额为：" + userWallet + "，续费所需金额为：" + price.negate();
        }
        if(StringUtils.isBlank(message.getNoticeContent())) {
            // 创建订单
            CnOrderItem orderItem = createOrder(serversRelation, sysUser, price);

            // 扣除余额
            cnWalletLogService.updateUserBalanceAndLog(userId,
                    price, PaymentMethodEnum.WALLET.name(), null, orderItem.getShoppingCarEnums()
                    , orderItem.getSn(), "autoRenew");
            content = "您的资源" + orderItem.getOrderAbstract() + "已申请,订单编号为：" + orderItem.getSn() + "。请及时关注订单状态。";
        }
        // 发送消息
        message.setNoticeContent(content);
        sysMessageService.addSysMessage(message);

        // 发送邮件
        //获取用户邮箱地址
        String email = userMapper.getEmailByUserId(userId);
        emailSendService.sendMessage(new EmailSendDTO(email, title, EmailTypeEnum.AUTOMATIC_RENEWAL, serversRelation.getOrderAbstract()));
    }

    /**
     * 生成订单
     *
     * @param cnUserCloudServersRelation 用户关系表
     */
    private CnOrderItem createOrder(CnUserCloudServersRelation cnUserCloudServersRelation, SysUser sysUser, BigDecimal price) {
        Date date = new Date();

        Long orderId = SnowFlakeUtil.getSnowFlakeId();
        Long orderItemId = SnowFlakeUtil.getSnowFlakeId();
        Integer periodNum = cnUserCloudServersRelation.getPeriodNum();
        Integer periodType = cnUserCloudServersRelation.getPeriodType();

        // 子订单项
        CnOrderItem cnOrderItem = genCnOrderItem(cnUserCloudServersRelation);

        BigDecimal totalOriginalPrice = price; // 总原始价格
        BigDecimal totalDiscountPrice = BigDecimal.ZERO; // 总优惠价格
        BigDecimal totalUpdatePrice = price; // 总修改后价格

        cnOrderItem.setOrderItemId(orderItemId.toString());
        cnOrderItem.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
        cnOrderItem.setOrderId(orderId);
        cnOrderItem.setUserId(cnUserCloudServersRelation.getUserId());
        cnOrderItem.setCreateTime(date);
        cnOrderItem.setCnUserCloudServersRelationId(cnUserCloudServersRelation.getId());
        cnOrderItem.setInvoicing("0");
        cnOrderItem.setContractStatus("0");

        // 订单
        CnOrder cnOrder = new CnOrder();
        cnOrder.setOrderId(orderId);
        cnOrder.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
        cnOrder.setUserId(cnUserCloudServersRelation.getUserId());
        cnOrder.setUserName(sysUser.getNickName());
        cnOrder.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
        cnOrder.setShoppingCarType(OrderTypeEnum.SYSTEM.name());

        // 生成订单号
        cnOrder.setSn("SN" + SnowFlakeUtil.getSnowFlakeId());
        cnOrder.setPaymentTime(date);
        cnOrder.setOriginalPrice(totalOriginalPrice);
        cnOrder.setDiscountPrice(totalDiscountPrice);
        cnOrder.setUpdatePrice(totalUpdatePrice);
        cnOrder.setPaymentMethod(PaymentMethodEnum.WALLET.name());
        cnOrder.setOrderAbstract("资源：【" + cnUserCloudServersRelation.getOrderAbstract().split("【")[1].split("】")[0] + "】自动续费");
        orderService.save(cnOrder);

        cnOrderItem.setSn(cnOrder.getSn());
        cnOrderItem.setOrderAbstract(cnOrder.getOrderAbstract());
        cnOrderItem.setShoppingCarType(cnOrder.getShoppingCarType());
        cnOrderItem.setShoppingCarType(cnOrder.getShoppingCarType());
        cnOrderItem.setRelationId(cnUserCloudServersRelation.getRelationId());
        cnOrderItem.setPeriodNum(1);

        if(cnUserCloudServersRelation.getShoppingCarEnums() == ShoppingCarEnums.CLOUD_SERVER){

            // 查询当前规格的价格
            List<PeriodProductInfo> productInfos = JSONArray.parseArray(cnUserCloudServersRelation.getPriceQueryJsonStr(), PeriodProductInfo.class);
            productInfos.stream().forEach(v -> {
                v.setPeriodNum(1);
                v.setPeriodType(periodType > 30 ? 3 : 2);
            });

            List<PeriodProductInfo> ec2List = productInfos.stream().filter(item -> item.getResourceType().equals("hws.resource.type.vm")).collect(Collectors.toList());
            List<PeriodProductInfo> ebsList = productInfos.stream().filter(item -> item.getResourceType().equals("hws.resource.type.volume")).collect(Collectors.toList());
            List<PeriodProductInfo> vpcList = productInfos.stream().filter(item -> item.getResourceType().equals("hws.resource.type.bandwidth")).collect(Collectors.toList());

            BigDecimal ec2Price = BigDecimal.ZERO;
            BigDecimal ebsPrice = BigDecimal.ZERO;
            BigDecimal vpcPrice = BigDecimal.ZERO;

            if(ec2List.size() != 0){
                RateOnPeriodReqDTO ec2Dto = new RateOnPeriodReqDTO();
                ec2Dto.setProductInfos(ec2List);
                Map<String, Object> stringObjectMap = cloudServiceService.listRateOnPeriodDetail(ec2Dto);
                ec2Price = (BigDecimal)stringObjectMap.get("price");
            }
            if(ebsList.size() != 0){
                RateOnPeriodReqDTO ebsDto = new RateOnPeriodReqDTO();
                ebsDto.setProductInfos(ebsList);
                Map<String, Object> stringObjectMap = cloudServiceService.listRateOnPeriodDetail(ebsDto);
                ebsPrice = (BigDecimal)stringObjectMap.get("price");
            }
            if(vpcList.size() != 0){
                RateOnPeriodReqDTO vpcDto = new RateOnPeriodReqDTO();
                vpcDto.setProductInfos(vpcList);
                Map<String, Object> stringObjectMap = cloudServiceService.listRateOnPeriodDetail(vpcDto);
                vpcPrice = (BigDecimal)stringObjectMap.get("price");
            }
            cnOrderItem.setEc2Price(ec2Price);
            cnOrderItem.setEbsPrice(ebsPrice);
            cnOrderItem.setVpcPrice(vpcPrice);
        }
        // 保存子订单
        orderItemService.save(cnOrderItem);

        return cnOrderItem;
    }

    /**
     * 生成订单项
     *
     * @param cnUserCloudServersRelation 用户关系表
     * @return
     */
    private CnOrderItem genCnOrderItem(CnUserCloudServersRelation cnUserCloudServersRelation) {
        CnOrderItem cnOrderItem = new CnOrderItem();
        BeanUtils.copyProperties(cnUserCloudServersRelation, cnOrderItem);
        cnOrderItem.setShoppingCarType(OrderTypeEnum.SYSTEM.name());
        return cnOrderItem;
    }

    /**
     * 查询用户-弹性云服务器关系
     *
     * @param userId 用户-弹性云服务器关系主键
     * @return 用户-弹性云服务器关系
     */
    @Override
    public CnUserCloudServersRelation selectCnUserCloudServersRelationByUserId(String userId) {
        return getById(userId);
    }

    /**
     * 新增用户-弹性云服务器关系
     *
     * @param cnUserCloudServersRelation 用户-弹性云服务器关系
     * @return 结果
     */
    @Override
    public boolean insertCnUserCloudServersRelation(CnUserCloudServersRelation cnUserCloudServersRelation) {
        return save(cnUserCloudServersRelation);
    }

    /**
     * 修改用户-弹性云服务器关系
     *
     * @param cnUserCloudServersRelation 用户-弹性云服务器关系
     * @return 结果
     */
    @Override
    public boolean updateCnUserCloudServersRelation(CnUserCloudServersRelation cnUserCloudServersRelation) {
        return updateById(cnUserCloudServersRelation);
    }

    /**
     * 批量删除用户-弹性云服务器关系
     *
     * @param userIds 需要删除的用户-弹性云服务器关系主键
     * @return 结果
     */
    @Override
    public boolean deleteCnUserCloudServersRelationByUserIds(List<String> userIds) {
        return removeBatchByIds(userIds);
    }

    /**
     * 删除用户-弹性云服务器关系信息
     *
     * @param userId 用户-弹性云服务器关系主键
     * @return 结果
     */
    @Transactional
    @Override
    public boolean deleteCnUserCloudServersRelationByUserId(String userId) {
        return removeById(userId);
    }

    @Override
    public void updateCloudServiceStatusByServerIds(List<ServerId> servers, ServerStatusEnum statusEnum) {
        List<String> serviceIds = servers.stream().map(ServerId::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<CnUserCloudServersRelation> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(CnUserCloudServersRelation::getRelationId, serviceIds);
        updateWrapper.set(CnUserCloudServersRelation::getStatus, statusEnum);
        update(updateWrapper);
    }

    @Override
    public List statisticsStatus(CnUserCloudServersRelation cnUserCloudServersRelation) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (!loginUser.getUser().getUserType().equals(UserConstants.USER_TYPE_MANAGER)) {
            // 查询用户购买的服务器
            cnUserCloudServersRelation.setUserId(SecurityUtils.getUserId());
        }
        return baseMapper.statisticsStatus(cnUserCloudServersRelation);
    }

    @Override
    public void buyAgain(String cloudServersId) {
        CnUserCloudServersRelation cloudServersRelation = this.getById(cloudServersId);
        String orderItemId = cloudServersRelation.getOrderItemId();
        CnOrderItem orderItem = orderItemService.getById(orderItemId);

        CnShoppingCar cnShoppingCar = new CnShoppingCar();
        cnShoppingCar.setUserId(cloudServersRelation.getUserId());
        cnShoppingCar.setJsonStr(orderItem.getJsonStr());
        cnShoppingCar.setAutoRenew(orderItem.getAutoRenew());
        cnShoppingCar.setOrderAbstract(orderItem.getOrderAbstract());
        cnShoppingCar.setOriginalPrice(orderItem.getOriginalPrice());
        cnShoppingCar.setUpdatePrice(orderItem.getOriginalPrice());
        cnShoppingCar.setPeriodType(orderItem.getPeriodType());
        cnShoppingCar.setPeriodNum(orderItem.getPeriodNum());
        cnShoppingCar.setDiscount(10);
        cnShoppingCar.setPriceQueryJsonStr(orderItem.getPriceQueryJsonStr());
        cnShoppingCar.setShoppingCarEnums(ShoppingCarEnums.CLOUD_SERVER);

        cnShoppingCarService.save(cnShoppingCar);
    }

    /**
     * 更新云服务器配置信息
     */
    @Override
    public void execute(String userServersId) {
        log.info("执行更新云服务器配置信息");
        CnUserCloudServersRelation cnUserCloudServersRelation = this.getById(userServersId);
        ListServersDetailsRequestDTO dto = new ListServersDetailsRequestDTO();
        dto.setServerId(cnUserCloudServersRelation.getRelationId());
        // 查询
        ListServersDetailsResponse response = cloudControlService.listServersDetails(dto);
        cnUserCloudServersRelation.setJsonStr(JsonUtils.toJSON(response));
        this.updateById(cnUserCloudServersRelation);
        log.info("执行更新云服务器配置信息结束");
    }
}
